
package com.task.base;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.view.*;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.*;

import java.util.HashMap;
import java.util.List;

public class ProcessActivity extends ListActivity {

    private Context context = null;

    private long totalLoad, totalDelta, totalWork, workDelta;

    private static final int MSG_INIT_OK = 6;

    private static final int MSG_MENU_DISMISS = 0;

    private PackageManager mPm;

    private ActivityManager am;

    private TextView process;

    private TextView memory;

    private byte[] buf = new byte[512];

    public static final int ITEM_SWITCH = 0;

    public static final int ITEM_KILL = 1;

    public static final int ITEM_UNINSTALL = 2;

    public static final int ITEM_DETAIL = 3;

    public int processSoftBy;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.process);
        am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        mPm = getPackageManager();

        process = (TextView) findViewById(R.id.processCount);
        memory = (TextView) findViewById(R.id.availableMemory);
        context = this;
        initList();
        registerForContextMenu(getListView());

        Button buttonAllOver = (Button) findViewById(R.id.buttonAllOver);
        buttonAllOver.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Util.killAllProcess(context);
                updateListData();

            }
        });
    }

    /**
     * 初始化进程列表
     */
    private void initList() {
        ArrayAdapter<ProcessItem> adapter = new ArrayAdapter<ProcessItem>(this, R.layout.list_item) {

            public android.view.View getView(int position, android.view.View convertView,
                    android.view.ViewGroup parent) {
                View view;
                TextView txt_name, txt_mem, txt_cpu;
                ImageView img_type;
                ImageButton closeButton;

                if (convertView == null) {
                    view = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
                } else {
                    view = convertView;
                }

                if (position >= getCount()) {
                    return view;
                }

                ProcessItem itm = getItem(position);

                img_type = (ImageView) view.findViewById(R.id.itemImage);
                txt_name = (TextView) view.findViewById(R.id.name);
                txt_mem = (TextView) view.findViewById(R.id.infoMem);
                txt_cpu = (TextView) view.findViewById(R.id.infoCpu);
                closeButton = (ImageButton) view.findViewById(R.id.buttonClose);
                txt_name.setTag(itm);
                String lb = itm.label;
                if (itm.sys) {
                    lb += " *";
                }
                txt_name.setText(lb);
                closeButton.setTag(itm.packageName);
                img_type.setImageDrawable(itm.icon);

                txt_mem.setText(itm.mem + ",");
                txt_cpu.setText(itm.cupValue + "%");
                closeButton.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        String packageName = (String) v.getTag();
                        try {
                            am.restartPackage(packageName);
                            // am.forceStopPackage(packageName);//强制关闭，用于中兴手机
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        updateListData();
                    }
                });
                closeButton.setFocusable(false);// 由于按钮会和listView抢夺焦点所有需要设置一下
                view.setTag(itm);
                return view;
            }
        };
        getListView().setAdapter(adapter);
    }

    // @Override
    // public boolean onCreateOptionsMenu(Menu menu) {
    // super.onCreateOptionsMenu(menu);
    // menu.add(0, 1, 1,
    // R.string.settings).setIcon(R.drawable.ic_menu_settings);
    // menu.add(0, 2, 2, R.string.sort).setIcon(R.drawable.ic_menu_sort);
    // // menu.add(0, 3, 3, R.string.traffic).setIcon(R.drawable.ic_menu_sort);
    // return true;
    // }
    private PopupWindow menuPopup;

    private View menuLayout;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add("menu");// 必须添加一个，其实用不到

        if (null == menuPopup) {

            menuLayout = getLayoutInflater().inflate(R.layout.options_menu_process, null);

            menuPopup = new PopupWindow(menuLayout, LayoutParams.FILL_PARENT,
                    LayoutParams.WRAP_CONTENT);

            menuPopup.setFocusable(true);// 必须，否则无法点击子view
            menuPopup.setOutsideTouchable(true);// 必须，否则点击其它区域无法关闭
            menuPopup.setBackgroundDrawable(new BitmapDrawable());// 同上
            menuPopup.setAnimationStyle(R.style.MenuAnimation);

            menuPopup.setTouchInterceptor(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getY() < 0) {
                        if (menuPopup.isShowing())
                            menuPopup.dismiss();
                    }
                    return false;
                }
            });

            menuLayout.setFocusableInTouchMode(true);// 必须，否则下面的事件不起作用

            menuLayout.setOnKeyListener(new OnKeyListener() {
                @Override
                public boolean onKey(View v, int keyCode, KeyEvent event) {
                    if ((keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK)
                            && (menuPopup.isShowing())) {
                        menuPopup.dismiss();
                        return true;
                    }
                    return false;
                }
            });

            ((Button) menuLayout.findViewById(R.id.menu_settings))
                    .setOnClickListener(new OnClickListener() {
                        public void onClick(View v) {
                            handler.sendEmptyMessage(MSG_MENU_DISMISS);
                            Intent intent = new Intent(ProcessActivity.this, SettingActivity.class);
                            startActivity(intent);
                        }
                    });

            ((Button) menuLayout.findViewById(R.id.menu_sort))
                    .setOnClickListener(new OnClickListener() {
                        public void onClick(View v) {
                            handler.sendEmptyMessage(MSG_MENU_DISMISS);
                            ProcessActivity.this.getListDialog(ProcessActivity.this,
                                    getResources().getString(R.string.sort), R.array.sort,
                                    R.drawable.icon).show();
                        }
                    });

        }

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (menuPopup.isShowing())
            menuPopup.dismiss();
        else
            menuPopup.showAtLocation(findViewById(R.id.layoutRoot), Gravity.BOTTOM, 0, 0);
        return false;
    }

    public Dialog getListDialog(final Context context, String title, final int itemsId, int icon) {
        return new AlertDialog.Builder(context)
                .setIcon(icon)
                .setTitle(title)
                .setSingleChoiceItems(itemsId, processSoftBy,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                switch (which) {
                                    case ProcessSortComparator.sortByCpu:
                                        processSoftBy = ProcessSortComparator.sortByCpu;
                                        sort(ProcessSortComparator.sortByCpu);
                                        dialog.dismiss();
                                        break;
                                    case ProcessSortComparator.sortByMemory:
                                        processSoftBy = ProcessSortComparator.sortByMemory;
                                        sort(ProcessSortComparator.sortByMemory);
                                        dialog.dismiss();
                                        break;
                                }
                            }
                        })
                .setNegativeButton(getResources().getString(R.string.cancel),
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                            }

                        }).create();
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {

        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
        ProcessItem item = (ProcessItem) info.targetView.getTag();
        if (item != null) {
            menu.setHeaderIcon(item.icon);
            menu.setHeaderTitle(item.label);
            menu.add(0, ITEM_SWITCH, 0, R.string.switch_process);
            menu.add(0, ITEM_KILL, 1, R.string.end_process);
            if (!item.sys) {
                menu.add(0, ITEM_UNINSTALL, 2, R.string.uninstall);
            }
            menu.add(0, ITEM_DETAIL, 3, R.string.detail);
        }
        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {

        AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
        ProcessItem itm = (ProcessItem) menuInfo.targetView.getTag();
        String packageName = itm.packageName;

        switch (item.getItemId()) {
            case ITEM_SWITCH:
                Util.runApplication(packageName, mPm, context);
                break;
            case ITEM_KILL:
                if (itm.sys) {
                    showCannotEndDialog();
                    break;
                }
                Util.killProcess(packageName, am, context);
                updateListData();
                break;
            case ITEM_UNINSTALL:
                Util.unintallApplication(packageName, context);
                break;
            case ITEM_DETAIL:
                Util.runApplicationDetails(packageName, context);
                break;
        }
        return super.onContextItemSelected(item);
    }

    private void showCannotEndDialog() {
        new AlertDialog.Builder(context).setIcon(R.drawable.recycle)
                .setTitle(R.string.alert_dialog_msg).setMessage(R.string.alert_dialog_msg)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        return;
                    }
                }).create().show();
    }

    Runnable task = new Runnable() {

        public void run() {
            updateListData();
            handler.sendEmptyMessage(MSG_INIT_OK);
        }
    };

    Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case MSG_INIT_OK:
                    handler.postDelayed(task, 10000);
                    break;
                case MSG_MENU_DISMISS:
                    if (menuPopup != null && menuPopup.isShowing()) {
                        menuPopup.dismiss();
                    }
                    break;

            }
        };
    };

    @Override
    protected void onResume() {
        super.onResume();
        handler.post(task);

        if (menuPopup != null && menuPopup.isShowing())
            menuPopup.dismiss();

    }

    @Override
    protected void onPause() {
        handler.removeCallbacks(task);
        handler.removeMessages(MSG_INIT_OK);
        super.onPause();
    }

    private HashMap<Integer, Long> processCpu = new HashMap<Integer, Long>();

    /**
     * 更新list中数据。
     * 
     * @throws NameNotFoundException
     */
    private void updateListData() {
        List<RunningAppProcessInfo> raps = am.getRunningAppProcesses();

        String[] memoryInfo = Util.getMemoryInfo(this);
        memory.setText(memoryInfo[0] + "/" + memoryInfo[1]);

        updateCpuInfo();

        ArrayAdapter<ProcessItem> adapter = (ArrayAdapter<ProcessItem>) getListView().getAdapter();
        processCpu.clear();
        int pid = 0;
        for (int i = 0; i < adapter.getCount(); i++) {
            pid = adapter.getItem(i).pid;
            if (pid > 0) {
                processCpu.put(pid, adapter.getItem(i).cputime);
            }
        }

        adapter.setNotifyOnChange(false);
        adapter.clear();

        ProcessItem currentItem = null;
        boolean isSys = false;
        for (RunningAppProcessInfo process : raps) {
            currentItem = new ProcessItem();
            String processName = process.processName;
            currentItem.label = processName;
            ApplicationInfo applicationInfo;
            try {
                applicationInfo = mPm.getApplicationInfo(processName,
                        PackageManager.GET_UNINSTALLED_PACKAGES);
            } catch (NameNotFoundException e) {
                continue;
            }
            currentItem.icon = getIcon(applicationInfo);

            // 判断是否系统程序
            isSys = Util.isSystemApplication(processName);
            currentItem.sys = isSys;

            // 如果是进程
            currentItem.pid = process.pid;
            if (processCpu.containsKey(currentItem.pid)) {
                currentItem.lastcputime = processCpu.get(currentItem.pid);
            }
            // 获取内存肯时间
            Util.readProcessStat(context, buf, currentItem);
            currentItem.packageName = process.processName;
            currentItem.label = getProcessName(applicationInfo);
            // 计算一定要在获取数据以后
            long delta = currentItem.lastcputime == 0 ? 0
                    : (currentItem.cputime - currentItem.lastcputime);
            long cu = totalDelta == 0 ? 0 : (delta * 100 / totalDelta);

            if (cu < 0) {
                cu = 0;
            }
            if (cu > 100) {
                cu = 100;
            }
            currentItem.cupValue = cu;
            if (!currentItem.sys && !getPackageName().equals(currentItem.packageName)) {
                adapter.add(currentItem);
            }
        }
        process.setText(" " + adapter.getCount() + "");
        processCpu.clear();
        sort(processSoftBy);
        adapter.notifyDataSetChanged();

    }

    private Drawable getIcon(ApplicationInfo applicationInfo) {

        if (applicationInfo != null) {
            Drawable icon = mPm.getApplicationIcon(applicationInfo);
            if (icon == null) {
                try {
                    icon = mPm.getDefaultActivityIcon();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return icon;
        }
        return null;
    }

    private String getProcessName(ApplicationInfo ai) {

        if (ai != null) {
            CharSequence label = mPm.getApplicationLabel(ai);
            if (label != null) {
                return label.toString();
            }
        }
        return "";
    }

    private ProcessSortComparator processSortComparator = new ProcessSortComparator(processSoftBy);

    private void sort(int sortBy) {

        ArrayAdapter<ProcessItem> adapter = (ArrayAdapter<ProcessItem>) getListView().getAdapter();
        processSortComparator.setSortBy(sortBy);
        adapter.sort(processSortComparator);
    }

    /**
     * 更新获取总体CPU使用时间。
     */
    private void updateCpuInfo() {

        long[] loads = Util.readCpuLoad();
        long newload = loads == null ? 0 : (loads[0] + loads[1]);

        if (totalLoad != 0) {
            totalDelta = newload - totalLoad;
        }
        totalLoad = newload;
        long newWork = loads == null ? 0 : loads[0];

        if (totalWork != 0) {
            workDelta = newWork - totalWork;
        }
        totalWork = newWork;
    }

    /**
     * 获取cpu使用率，单位是百分比。
     * 
     * @return
     */
    public long getCpuUsage() {
        long cpu = totalDelta == 0 ? 0 : (workDelta * 100 / totalDelta);

        if (cpu < 0) {
            cpu = 0;
        }
        if (cpu > 100) {
            cpu = 100;
        }
        return cpu;
    }
}
